package md5_generator

import (
	"crypto/md5"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"time"
)

func Md5_generator() {
	if len(os.Args) != 2 {
		fmt.Println("请拖动一个目录到此程序上。\n")
		fmt.Println("此程序由信息技术部提供技术支持。\n")
		time.Sleep(5 * time.Second)
		return
	}

	targetPath := os.Args[1]
	err := processPath(targetPath)
	if err != nil {
		fmt.Printf("处理路径时出错: %v\n", err)
		time.Sleep(5 * time.Second)
		return
	}

}

func processPath(path string) error {
	var files []string
	lastDir := filepath.Base(path)

	// 检查路径是文件还是目录
	info, err := os.Stat(path)
	if err != nil {
		return err
	}

	if info.IsDir() {
		// 如果是目录，则遍历目录下的所有文件
		err = filepath.Walk(path, func(filePath string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if !info.IsDir() {
				files = append(files, filePath)
			}
			return nil
		})
		if err != nil {
			return err
		}
	} else {
		// 如果是文件，直接添加到文件列表
		return fmt.Errorf("请拖动一个目录，而不是文件")
	}

	// 生成 index.txt 的路径（在程序所在目录）
	executablePath, err := os.Executable()
	if err != nil {
		return err
	}
	executableDir := filepath.Dir(executablePath)
	outputdir := filepath.Join(executableDir, lastDir)
	if _, err := os.Stat(outputdir); os.IsNotExist(err) {
		// 如果目录不存在，则创建目录
		err := os.MkdirAll(outputdir, os.ModePerm)
		if err != nil {
			fmt.Printf("创建目录时出错: %v\n", err)
			return err
		}
	}

	indexFilePath := filepath.Join(outputdir, "index.txt")
	err = writeMD5ToFile(files, indexFilePath, path)
	if err != nil {
		return err
	}

	// 计算 index.txt 的 MD5
	indexMD5Hash, err := calculateMD5(indexFilePath)
	if err != nil {
		return err
	}

	// 生成 index.md5 的路径（在程序所在目录）
	indexMD5FilePath := filepath.Join(outputdir, "index_md5")

	fmt.Printf("MD5 校验码已生成并写入 \"%s\"目录下 index.txt 和 index.md5\n", outputdir)
	time.Sleep(5 * time.Second)
	return writeMD5ToFileForIndexMD5(indexMD5FilePath, indexMD5Hash)
}

func writeMD5ToFile(files []string, indexFilePath string, rootPath string) error {

	lastDir := filepath.Base(rootPath)
	outputFile, err := os.Create(indexFilePath)
	if err != nil {
		return err
	}
	defer outputFile.Close()

	for _, file := range files {
		md5Hash, err := calculateMD5(file)
		if err != nil {
			return err
		}
		// 使用相对路径写入 index.txt
		relativePath, err := filepath.Rel(rootPath, file)
		if err != nil {
			return err
		}
		_, err = outputFile.WriteString(fmt.Sprintf("文件: \"%s\\%s\"\t\t\tMD5: %x\n", lastDir, relativePath, md5Hash))
		if err != nil {
			return err
		}
	}

	return nil
}

func writeMD5ToFileForIndexMD5(indexMD5FilePath string, md5Hash [16]byte) error {
	outputFile, err := os.Create(indexMD5FilePath)
	if err != nil {
		return err
	}
	defer outputFile.Close()

	_, err = outputFile.WriteString(fmt.Sprintf("index.txt: %x\n", md5Hash))
	return err
}

func calculateMD5(filePath string) ([16]byte, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return [16]byte{}, err
	}
	defer file.Close()

	hasher := md5.New()
	if _, err := io.Copy(hasher, file); err != nil {
		return [16]byte{}, err
	}

	return [16]byte(hasher.Sum([]byte{})), nil
}
